#!/usr/bin/env bun
/**
 * 为现有的 n8n 节点分配推荐值
 *
 * 使用方法：
 * bun run scripts/assign-node-recommend-values.ts
 */

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// 核心节点定义（推荐值 10）- 使用实际的节点名称
const CORE_NODES = [
  'n8n-nodes-base.httpRequest',
  'n8n-nodes-base.code',
  'n8n-nodes-base.if',
  'n8n-nodes-base.set',
  'n8n-nodes-base.editFields',
  'n8n-nodes-base.switch',
  'n8n-nodes-base.merge',
  'n8n-nodes-base.function',
  'n8n-nodes-base.functionItem',
  'n8n-nodes-base.executeWorkflow',
  'n8n-nodes-base.start',
  'n8n-nodes-base.emailSend',
  'n8n-nodes-base.dateTime',
  'n8n-nodes-base.compareDatasets',
  'n8n-nodes-base.itemLists',
  'n8n-nodes-base.sort',
  'n8n-nodes-base.limit',
];

// 高频使用节点（推荐值 9）
const HIGH_FREQUENCY_NODES = [
  '@n8n/n8n-nodes-langchain.agent',
  '@n8n/n8n-nodes-langchain.agentTool',
  '@n8n/n8n-nodes-langchain.memoryBufferWindow',
  '@n8n/n8n-nodes-langchain.chatTrigger',
  'n8n-nodes-base.postgres',
  'n8n-nodes-base.redis',
  'n8n-nodes-base.webhook',
  'n8n-nodes-base.wait',
  'n8n-nodes-base.splitInBatches',
  'n8n-nodes-base.loopOverItems',
  'n8n-nodes-base.rssFeedRead',
  'n8n-nodes-base.xml',
  'n8n-nodes-base.json',
  'n8n-nodes-base.csv',
  'n8n-nodes-base.htmlExtract',
  'n8n-nodes-base.postBin',
  '@n8n/n8n-nodes-langchain.toolVectorStore',
  '@n8n/n8n-nodes-langchain.vectorStoreInMemory',
  '@n8n/n8n-nodes-langchain.vectorStorePGVector',
];

// 常用云服务节点（推荐值 8）
const CLOUD_SERVICE_NODES = [
  'n8n-nodes-base.awsS3',
  'n8n-nodes-base.googleDrive',
  'n8n-nodes-base.dropbox',
  'n8n-nodes-base.microsoftOneDrive',
  'n8n-nodes-base.amazonSes',
  'n8n-nodes-base.sendGrid',
  'n8n-nodes-base.mailgun',
  'n8n-nodes-base.twilio',
  'n8n-nodes-base.slack',
  'n8n-nodes-base.discord',
  'n8n-nodes-base.microsoftTeams',
  'n8n-nodes-base.telegram',
];

// 通用数据库节点（推荐值 8）
const DATABASE_NODES = [
  'n8n-nodes-base.mySql',
  'n8n-nodes-base.postgres',
  'n8n-nodes-base.mongoDb',
  'n8n-nodes-base.redis',
  'n8n-nodes-base.sqlite',
  'n8n-nodes-base.microsoftSql',
  'n8n-nodes-base.questDb',
  'n8n-nodes-base.cockroachDb',
];

// 通用API节点（推荐值 7）- 已在核心节点中包含httpRequest
const API_NODES = ['n8n-nodes-base.graphql', 'n8n-nodes-base.soapRequest'];

// 文件处理节点（推荐值 6）
const FILE_PROCESSING_NODES = [
  'n8n-nodes-base.readBinaryFile',
  'n8n-nodes-base.writeBinaryFile',
  'n8n-nodes-base.readBinaryFiles',
  'n8n-nodes-base.writeBinaryFiles',
  'n8n-nodes-base.ftp',
  'n8n-nodes-base.sftp',
  'n8n-nodes-base.moveFiles',
];

// 类别映射推荐值
const CATEGORY_RECOMMEND_VALUES: Record<string, number> = {
  core: 8,
  input: 7,
  output: 7,
  transform: 6,
  cloud: 6,
  communication: 6,
  development: 5,
  files: 5,
  analytics: 4,
  marketing: 4,
  other: 3,
};

async function assignRecommendValues() {
  console.log('🚀 开始为 n8n 节点分配推荐值...');

  try {
    // 获取所有节点
    const allNodes = await prisma.nodeType.findMany({
      select: {
        id: true,
        name: true,
        displayName: true,
        category: true,
        recommendValue: true,
      },
    });

    console.log(`📋 发现 ${allNodes.length} 个节点需要处理`);

    let updatedCount = 0;
    const updates: Array<{ nodeId: number; newValue: number; reason: string }> = [];

    for (const node of allNodes) {
      let newRecommendValue: number;
      let reason: string;

      // 1. 检查核心节点
      if (CORE_NODES.includes(node.name)) {
        newRecommendValue = 10;
        reason = '核心节点';
      }
      // 2. 检查高频使用节点
      else if (HIGH_FREQUENCY_NODES.includes(node.name)) {
        newRecommendValue = 9;
        reason = '高频使用节点';
      }
      // 3. 检查云服务节点
      else if (CLOUD_SERVICE_NODES.includes(node.name)) {
        newRecommendValue = 8;
        reason = '云服务节点';
      }
      // 4. 检查数据库节点
      else if (DATABASE_NODES.includes(node.name)) {
        newRecommendValue = 8;
        reason = '数据库节点';
      }
      // 5. 检查API节点
      else if (API_NODES.includes(node.name)) {
        newRecommendValue = 7;
        reason = 'API节点';
      }
      // 6. 检查文件处理节点
      else if (FILE_PROCESSING_NODES.includes(node.name)) {
        newRecommendValue = 6;
        reason = '文件处理节点';
      }
      // 7. 根据类别分配
      else if (node.category && CATEGORY_RECOMMEND_VALUES[node.category] !== undefined) {
        newRecommendValue = CATEGORY_RECOMMEND_VALUES[node.category]!;
        reason = `类别: ${node.category}`;
      }
      // 8. 根据名称关键词智能分配
      else {
        newRecommendValue = calculateSmartRecommendValue(node.name, node.displayName);
        reason = '智能分析';
      }

      // 只有当推荐值改变时才更新
      if (newRecommendValue !== node.recommendValue) {
        updates.push({
          nodeId: node.id,
          newValue: newRecommendValue,
          reason: reason,
        });
      }
    }

    console.log(`📊 需要更新 ${updates.length} 个节点的推荐值`);

    // 批量更新
    for (const update of updates) {
      await prisma.nodeType.update({
        where: { id: update.nodeId },
        data: { recommendValue: update.newValue },
      });
      updatedCount++;

      if (updatedCount % 50 === 0) {
        console.log(`⏳ 已更新 ${updatedCount}/${updates.length} 个节点...`);
      }
    }

    // 统计结果
    const stats = await generateStats();

    console.log('\n✅ 推荐值分配完成！');
    console.log('\n📈 统计结果：');
    console.log(`   更新节点数: ${updatedCount}`);
    console.log(`   推荐值分布:`);
    for (const [value, count] of Object.entries(stats)) {
      console.log(`     ${value} 分: ${count} 个节点`);
    }

    // 输出前10个高推荐值节点
    const topNodes = await prisma.nodeType.findMany({
      select: {
        name: true,
        displayName: true,
        recommendValue: true,
        category: true,
      },
      orderBy: { recommendValue: 'desc' },
      take: 15,
    });

    console.log('\n🏆 推荐值最高的15个节点：');
    topNodes.forEach((node, index) => {
      console.log(
        `   ${index + 1}. ${node.displayName} (${node.name}) - ${node.recommendValue}分 [${
          node.category || 'N/A'
        }]`
      );
    });
  } catch (error) {
    console.error('❌ 处理失败:', error);
    process.exit(1);
  } finally {
    await prisma.$disconnect();
  }
}

function calculateSmartRecommendValue(name: string, displayName: string): number {
  const nameSearch = (name + ' ' + displayName).toLowerCase();

  // HTTP/API 相关
  if (nameSearch.includes('http') || nameSearch.includes('api') || nameSearch.includes('webhook')) {
    return 8;
  }

  // 数据库相关
  if (
    nameSearch.includes('database') ||
    nameSearch.includes('sql') ||
    nameSearch.includes('db') ||
    nameSearch.includes('mongo')
  ) {
    return 7;
  }

  // 通讯相关
  if (
    nameSearch.includes('email') ||
    nameSearch.includes('slack') ||
    nameSearch.includes('discord') ||
    nameSearch.includes('telegram')
  ) {
    return 6;
  }

  // 触发器和定时任务
  if (
    nameSearch.includes('trigger') ||
    nameSearch.includes('schedule') ||
    nameSearch.includes('cron')
  ) {
    return 6;
  }

  // 云服务
  if (
    nameSearch.includes('aws') ||
    nameSearch.includes('google') ||
    nameSearch.includes('microsoft') ||
    nameSearch.includes('azure')
  ) {
    return 5;
  }

  // 文件操作
  if (
    nameSearch.includes('file') ||
    nameSearch.includes('csv') ||
    nameSearch.includes('json') ||
    nameSearch.includes('xml')
  ) {
    return 5;
  }

  // 默认值
  return 4;
}

async function generateStats(): Promise<Record<string, number>> {
  const stats = await prisma.nodeType.groupBy({
    by: ['recommendValue'],
    _count: { recommendValue: true },
    orderBy: { recommendValue: 'desc' },
  });

  const result: Record<string, number> = {};
  for (const stat of stats) {
    result[stat.recommendValue.toString()] = stat._count.recommendValue;
  }

  return result;
}

// 执行脚本
if (import.meta.main) {
  assignRecommendValues().catch(console.error);
}
